package my.bc.webdav.client;

import java.util.HashMap;
import java.util.Map;

public class UriUtil
{
  /**
   * I used URI to escape uri, but there are a lot of other characters are not escaped, such as '&' '!' etc.
   * escape these characters here to avoid the difference.
   * @param uriStr
   * @return
   */
  
  private static char[] fullEscapeChars = new char[]{ ' ', '#', '$', '&', '&', '`', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '^',
                                                      '{', '|', '}', '~', '"', '+', ',', '!', '(', ')', '@' }; // '%', '\'', the % must put first
    
  //put '%' at the very beginning, in case escaped chars escape again.
  private static char[] deepEscapeChars = new char[]{'&',':',';','=','~','\'','+','!','(',')'};   //'/','%','$',
  //3$4%5&6/8:9;10=12~22\'24+25!26(27)28
  
  private static Map<Character, String> CharReplaceStringMap = new HashMap<Character, String>();
  
  public static String fullEscape( String uriStr )
  {
    return escapeChars( uriStr, fullEscapeChars );
  }
  
  public static String deepEscape( String uriStr )
  {
    return escapeChars( uriStr, deepEscapeChars );
  }
  
  public static String escapeChars( String uriStr, char[] escapingChars )
  {
    if( uriStr == null || uriStr.isEmpty() )
      return uriStr;
    for( char escapingChar : escapingChars )
    {
      uriStr = uriStr.replace( String.valueOf( escapingChar ), getReplaceString( escapingChar ) );
    }
    return toUtf8( uriStr );
  }
  
  private static String getReplaceString( char escapeChar )
  {
    String replaceString = CharReplaceStringMap.get( escapeChar );
    if( replaceString != null )
      return replaceString;

    int asciiCode = escapeChar;
    final String replaceString1 = String.format( "%%%X", asciiCode );

    synchronized( UriUtil.class )
    {
      replaceString = CharReplaceStringMap.get( escapeChar );
      if( replaceString != null )
        return replaceString;

      CharReplaceStringMap.put( escapeChar, replaceString1 );
    }
    return replaceString1;
  }

  public static String toUtf8( final String s )
  {
    try
    {
      byte bytes[] = s.getBytes( "UTF-8" );
      StringBuilder sb = new StringBuilder();
      
      for( byte b : bytes )
      {
        if( ( b & 0x80 ) != 0 )
          sb.append( String.format( "%%%X", b ) );
        else
          sb.append( (char)b );
      }
      return sb.toString();
    }
    catch( Exception e )
    {
      e.printStackTrace();
      return s;
    }
  }
}
